from django.shortcuts import render
from rest_framework.decorators import action
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import UpdateModelMixin, CreateModelMixin
from rest_framework import serializers
from django_redis import get_redis_connection
from rest_framework_jwt.views import ObtainJSONWebToken

from goods.models import SKU
from users import constants
from .models import User
from .serializers import CreateUserSerializer, UserDetailSerializer, EmailSerializer, UserAddressSerializer
from .serializers import SKUSerializer, AddressTitleSerializer, AddUserBrowsingHistorySerializer
from carts.utils import merge_cart_cookie_to_redis

# Create your views here.


class UsernameCountView(APIView):
    """
    判断用户名是否存在
    路由：usernames/(?P<username>\w{5,20})/count/
    """
    def get(self, request, username):
        count = User.objects.get(username=username).count()

        data = {
            'username': username,
            'count': count
        }

        return Response(data)


class MobileCountView(APIView):
    """
    判断手机号是否存在
    路由:mobiles/(?P<mobile>1[3-9]\d{9})/count/
    """
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()

        data = {
            'mobile': mobile,
            'count': count
        }

        return Response(data)


class UserView(CreateAPIView):
    """
    用户注册
    参数：username  password  password2  sms_code  mobile  allow
    """
    # 接收、校验参数(序列化器)
    # 保存用户数据到数据库(序列化器)
    # 返回响应(序列化器)
    serializer_class = CreateUserSerializer

    def post(self, request, *args, **kwargs):
        response = super().post(request, *args, **kwargs)
        user = self.user
        response = merge_cart_cookie_to_redis(request, response, user)

        return response


class UserDetailView(RetrieveAPIView):
    """
    用户中心个人信息
     GET /user/
    """
    serializer_class = UserDetailSerializer
    # 仅允许认证通过（登录之后）的用户访问该视图
    permission_classes = [IsAuthenticated]

    def get_object(self):
        # 获取当前登录的用户
        return self.request.user


class EmailView(UpdateAPIView):
    """
    保存邮箱并发送邮件
    PUT /email/
    """
    serializer_class = EmailSerializer
    permission_classes = [IsAuthenticated]

    def get_object(self):
        return self.request.user


class VerifyEmailView(APIView):
    """
    邮箱验证
    GET /emails/verification/?token=xxx
    """
    def get(self, request):
        # 获取token
        token = request.query_params.get('token')

        if not token:
            return Response({'message': '缺少token'}, status=status.HTTP_400_BAD_REQUEST)

        # 验证token
        user = User.check_email_token(token)
        if user is None:
            return Response({'message': '链接信息无效'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)
        else:
            # 表示该用户的邮箱已经验证
            user.email_active = True
            user.save()
            return Response({'message': 'OK'})


class AddressViewSet(GenericViewSet, CreateModelMixin, UpdateModelMixin):
    """
    用户地址
    """
    serializer_class = UserAddressSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # 获取当前登录用户的地址查询集
        return self.request.user.addresses.filter(is_deleted=False)

    def list(self, request):
        """GET /addresses/  查询所有地址"""
        query_set = self.get_queryset()
        s = self.get_serializer(query_set, many=True)
        user = self.request.user
        return Response({
            'user_id': user.id,
            # 用户的默认地址id
            'default_address_id': user.default_address_id,
            'limit': constants.USER_ADDRESS_COUNTS_LIMIT,
            'addresses': s.data
        })

    def create(self, request, *args, **kwargs):
        """POST /addresses/ 新建用户地址"""
        count = request.user.addresses.count()

        # 检查用户地址数据数目不能超过上限
        if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
            return Response({'message': '用户地址数量已达到上限'}, status=status.HTTP_400_BAD_REQUEST)

        return super().create(request, *args, **kwargs)

    # def update(self, request, *args, **kwargs):
    #     """PUT /addresses/<pk>/ 修改用户地址"""
    #     # self.update()会报错
    #     return super().update(request, *args, **kwargs)

    def destroy(self, request, pk):
        """DELETE /addresses/<pk>/  删除用户地址"""

        address = self.get_object()
        address.is_deleted = True
        address.save()

        return Response({'message': 'OK'}, status=status.HTTP_204_NO_CONTENT)

    @action(methods=['put'], detail=True)   # 对应：以路由对象的方式添加路由
    def status(self, request, pk):
        """PUT /addresses/<pk>/status/  设置默认地址"""
        address = self.get_object()
        self.request.user.default_address = address
        self.request.user.save()
        return Response({'message': 'OK'})

    @action(methods=['put'], detail=True)
    def title(self, request, pk):
        """PUT /addresses/<pk>/title/  设置地址标题"""
        address = self.get_object()
        s = AddressTitleSerializer(address, data=request.data)
        s.is_valid(raise_exception=True)
        s.save()
        return Response(s.data)


class UserBrowsingHistoryView(CreateAPIView):
    """
    用户浏览历史记录
    POST /browse_histories/
    """
    serializer_class = AddUserBrowsingHistorySerializer
    permission_classes = [IsAuthenticated]

    def get(self, request):
        """获取用户浏览历史记录"""
        user_id = request.user.id
        redis_conn = get_redis_connection('history')
        sku_id_list = redis_conn.lrange('history_%s' % user_id, 0, constants.USER_BROWSING_HISTORY_COUNTS_LIMIT-1)

        # 为了保持查询出的顺序与用户的浏览历史保存顺序一致
        sku_list = []
        for sku_id in sku_id_list:
            sku = SKU.objects.get(id=sku_id)
            sku_list.append(sku)

        s = SKUSerializer(sku_list, many=True)
        return Response(s.data)


class UserLoginView(ObtainJSONWebToken):
    """
    重写登录视图，合并购物车
    """
    def post(self, request, *args, **kwargs):
        # 调用父类的方法，获取drf jwt扩展默认的认证用户处理结果
        response = super().post(request, *args, **kwargs)

        # 仿照drf jwt扩展对于用户登录的认证方式，判断用户是否认证登录成功
        # 如果用户登录认证成功，则合并购物车
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            user = serializer.validated_data.get('user')
            response = merge_cart_cookie_to_redis(request, response, user)

        return response


